#pragma once
#include "Thread.hpp"
#include "Log.hpp"
#include "LockGuard.hpp"
#include <queue>

// 如何实现多进程的情况下的线程池

// 变量定义
int name_i = 0;

string ThreadName()
{
    string name = "thread-";
    name += to_string(name_i);
    name_i++;
    return name;
}

class ThreadData
{
    // 这个ThreadData感觉有点莫名其妙
public:
    ThreadData()
        : _thread_name(ThreadName()), _tid(0)
    {
    }
    string GetName() const { return _thread_name; }

private:
    pthread_t _tid;
    string _thread_name;
};

template <class T>
class ThreadPool
{
private:
public:
    ThreadPool(size_t thread_num = 5)
        : _thread_num(thread_num)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);

        for (size_t i = 0; i < _thread_num; i++)
        {
            ThreadData td;

            zhong::Thread<ThreadData> t(bind(&ThreadPool<T>::ThreadRun, this, td), td);
            _threads.push_back(t);
        }

        // 设置日志为写入对应文件
        log.LogOption(FileDiv);
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

    void CheckStatus()
    {
        _task_num = _queue.size();
        _thread_num = _threads.size();
        cout << "当前任务量为：" << _task_num << ", 当前线程量为：" << _thread_num << endl;
        // 是否需要增加新线程
        if (_task_num >= 50 && _thread_num <= 10)
        {
            ThreadData td;

            zhong::Thread<ThreadData> t(bind(&ThreadPool<T>::ThreadRun, this, td), td);
            _threads.push_back(t);
        }
        else if (_thread_num > 5)
        {
            pthread_t delete_tid = _threads.back().GetTid();
            _threads.pop_back();
            pthread_cancel(delete_tid);
        }
        else{
            cout << "当前任务量为：" << _task_num << ", 当前线程量为：" << _thread_num << endl;
        }
    }

    void ThreadRun(ThreadData &td)
    {
        while (1)
        {
            // T类型本质就是Task

            T task;
            // 获取任务
            {
                LockGuard guard(&_mutex);
                // 线程的动态控制
                CheckStatus();

                while (_queue.empty()) // 队列为空时，多个线程轮询判断等待
                {
                    ThreadWait();
                }
                task = _queue.front();
                _queue.pop();
            }
            // log.LogMessage(Debug, "the task is: %s\n", task.PrintTask().c_str());
            // 处理任务
            task();
            // log.LogMessage(Debug, "the task result is: %s\n", task.PrintResult().c_str());
        }
    }

    bool Start()
    {
        // log.LogMessage(Info, "the thread pool is starting\n");
        for (auto &thread : _threads)
        {
            thread.Start();
        }
        return true;
    }

    void Push(const T &in)
    {
        LockGuard guard(&_mutex);
        _queue.push(in);
        // 插入任务后可做唤醒线程了！
        ThreadWake();
    }
    bool Wait()
    {
        for (auto &thread : _threads)
        {
            thread.Join();
        }
        return true;
    }
    // 阻塞线程
    void ThreadWait()
    {
        // log.LogMessage(Info, "the thread is blocking\n");
        pthread_cond_wait(&_cond, &_mutex);
    }
    // 唤醒线程
    void ThreadWake()
    {
        // log.LogMessage(Info, "the thread is wake up\n");
        pthread_cond_signal(&_cond);
    }

private:
    // 线程池中的任务队列
    queue<T> _queue;
    // 存放线程的vector
    vector<zhong::Thread<ThreadData>> _threads;

    size_t _thread_num;

    // 信号机制
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;

    // 任务量
    size_t _task_num;

    Log log;
};
